package com.mysql;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.Vertx;
import io.vertx.core.impl.logging.Logger;
import io.vertx.core.impl.logging.LoggerFactory;
import io.vertx.core.net.NetClient;
import io.vertx.core.net.NetServer;
import io.vertx.core.net.NetSocket;

public class MySqlProxyServer {

    private static final Logger logger = LoggerFactory.getLogger(MySqlProxyServer.class);

    public static void main(String[] args) {
        Vertx.vertx().deployVerticle(new MysqlProxyServerVerticle());
    }

    public static class MysqlProxyServerVerticle extends AbstractVerticle {

        private final int port = 3306;
        private final String mysqlHost = "47.99.39.180";

        @Override
        public void start() throws Exception {

            NetServer netServer = vertx.createNetServer();//创建代理服务器
            NetClient netClient = vertx.createNetClient();//创建连接mysql客户端
            netServer.connectHandler(socket -> {

                socket.handler(buffer -> {
                    logger.info("buffer:" + buffer.toString());
                });


                netClient.connect(port, mysqlHost, result -> {
                    //响应来自客户端的连接请求，成功之后，在建立一个与目标mysql服务器的连接
                    if (result.succeeded()) {
                        logger.info("result:");
                        //与目标mysql服务器成功连接连接之后，创造一个MysqlProxyConnection对象,并执行代理方法
                        new MySqlProxyConnection(socket, result.result()).proxy();
                    } else {
                        socket.close();
                    }
                });
            }).listen(43306, listenResult -> {//代理服务器的监听端口
                if (listenResult.succeeded()) {
                    //成功启动代理服务器
                } else {
                    //启动代理服务器失败
                    System.exit(1);
                }
            });
        }
    }

    public static class MySqlProxyConnection {

        private final NetSocket clientSocket;
        private final NetSocket serverSocket;

        public MySqlProxyConnection(NetSocket clientSocket, NetSocket serverSocket) {
            this.clientSocket = clientSocket;
            this.serverSocket = serverSocket;
        }

        private void proxy() {
            //当代理与mysql服务器连接关闭时，关闭client与代理的连接
            serverSocket.closeHandler(v -> clientSocket.close());
            //反之亦然
            clientSocket.closeHandler(v -> serverSocket.close());
            //不管那端的连接出现异常时，关闭两端的连接
            serverSocket.exceptionHandler(e -> {
                logger.error(e.getMessage(), e);
                close();
            });
            clientSocket.exceptionHandler(e -> {
                logger.error(e.getMessage(), e);
                close();
            });
            //当收到来自客户端的数据包时，转发给mysql目标服务器
            clientSocket.handler(buffer -> {
                logger.info("处理客户端数据包");
                serverSocket.write(buffer);
            });
            //当收到来自mysql目标服务器的数据包时，转发给客户端
            serverSocket.handler(buffer -> {
                logger.info("处理服务端端数据包");
                clientSocket.write(buffer);
            });
        }

        private void close() {
            clientSocket.close();
            serverSocket.close();
        }
    }
}
